﻿/**
 * Copyright (C) 2012 original author and authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Runtime.Serialization;
using System.Reflection;
using System.Timers;

namespace NGuice.Inject.Internal.Util
{
    /// <summary>
    /// System.Collections.Concurrent.ConcurrentDictionary的构建器。他提供WeakReference
    /// 弱引用的key、value，以及按需计算的值，例如：
    /// <code>
    /// ConcurrentDictionary<Key, Graph> graphs = new MapMaker()
    ///          .ConcurrencyLevel(32)
    ///          .SoftKeys()
    ///          .WeakValues()
    ///          .Expiration(30, TimeUnit.MINUTES)
    ///          .MakeComputingMap(
    ///              new Function<Key, Graph>() {
    ///                  public Graph Apply(Key key) {
    ///                      return CreateExpensiveGraph(key);
    ///                  }
    ///              });
    ///          }
    /// </code>
    /// 这些特性都是可选的，<code>new MapMaker().MakeMap()</code>将返回一个有效的并发字典，这个
    /// 并发字典的行为非常类似ConcurrentDictionary，此返回的字典实现hash table却具有高性能。他
    /// 支持所有可选的ConcurrentDictionary接口的操作，但不允许null key或value，此字典是可序列化的。
    /// 但是，尽管如此，序列化弱引用的字典将引发不确定的结果。
    /// 默认的，返回的字典使用equals方法决定key和value是否相等。但是，如果WeakKeys被指定，字典将使用
    /// ==来替代key的比较，类似的，WeakValues如果被指定，字典将使用==比较value值。
    /// 字典中被垃圾回收器回收的实体将立即消失（如果默认的设置为强引用key或强引用value，这将永远不会发生）
    /// 。客户能够永远不监控一个部分回收的实体。所有字典中的实体都是当前获取时间的一个快照。
    /// </summary>
    public sealed class MapMaker
    {
        private Strength keyStrength;
        private Strength valueStrength;
        private long expirationNanos = 0;
        private bool useCustomMap;
        private readonly CustomConcurrentDictionary.Builder builder = new CustomConcurrentDictionary.Builder();

        public MapMaker()
        {
            keyStrength = new StrongStrength(this);
            valueStrength = new StrongStrength(this);
        }

        /// <summary>
        /// 设置一个自定义的初始化容量（默认16），重置任何类型的哈希表都将是一个相对缓慢的过程。
        /// 因此，如果可能，尽量不要改变表的大小
        /// </summary>
        /// <param name="initialCapacity"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">如果大小为负数,或已经设置</exception>
        public MapMaker InitialCapacity(int initialCapacity)
        {
            builder.InitialCapacity(initialCapacity);
            return this;
        }

        /// <summary>
        /// 设置自定义的加载因子（默认0.75）
        /// </summary>
        /// <param name="loadFactor"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">如果参数为非小数，或已经设置</exception>
        public MapMaker LoadFactor(float loadFactor)
        {
            builder.LoadFactor(loadFactor);
            return this;
        }

        /// <summary>
        /// 在更新操作期间允许的并发导航。用做内部大小的hint
        /// </summary>
        /// <param name="concurrencyLevel"></param>
        /// <returns></returns>
        public MapMaker ConcurrencyLevel(int concurrencyLevel)
        {
            builder.ConcurrencyLevel(concurrencyLevel);
            return this;
        }

        /// <summary>
        /// 指定存储在map中的每一个key（非value）应为WeakReference，默认使用强引用
        /// </summary>
        /// <returns></returns>
        public MapMaker WeakKeys()
        {
            return SetKeyStrength(new WeakStrength(this));
        }


        private MapMaker SetKeyStrength(Strength strength)
        {
            if (!keyStrength.Equals(new StrongStrength(this)))
            {
                throw new IllegalStateException("Key strength was already set to " + keyStrength + ".");
            }
            keyStrength = strength;
            useCustomMap = true;
            return this;
        }

        /// <summary>
        /// 指定map中每一个value（非key）应该为WeakReference弱引用（默认为强引用）
        /// </summary>
        /// <returns></returns>
        public MapMaker WeakValues()
        {
            return SetValueStrength(new WeakStrength(this));
        }

        private MapMaker SetValueStrength(Strength strength)
        {
            if (!new StrongStrength(this).Equals(valueStrength))
            {
                throw new IllegalStateException("Value strength was already set to " + valueStrength + ".");
            }
            valueStrength = strength;
            useCustomMap = true;
            return this;
        }

        /// <summary>
        /// 指定每一个实体都将在实体创建的一个固定期限后自动从map中删除
        /// </summary>
        /// <param name="duration">实体被创建后的一个日期长度</param>
        /// <param name="unit">时间单位</param>
        /// <returns></returns>
        /// <exception ref="ArgumentException">日期时限为负数</exception>
        /// <exception ref="IllegalStateException">日期时限已经设置</exception>
        public MapMaker Expiration(long duration, TimeSpan unit)
        {
            if (expirationNanos != 0)
            {
                throw new IllegalStateException("expiration time of " + expirationNanos + " ns was already set");
            }
            if (duration <= 0)
            {
                throw new ArgumentException("invalid duration: " + duration);
            }
            this.expirationNanos = TimeSpan.FromTicks(duration).Ticks;
            useCustomMap = true;
            return this;
        }

        /// <summary>
        /// 构建最终的字典，不具有后台计算的值
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="V"></typeparam>
        /// <returns></returns>
        public ConcurrentMap<K, V> MakeMap<K, V>()
           where K:class 
           //where V:class
        {
            return useCustomMap ? new StrategyImpl<K, V>(this).map : new ConcurrentHashDictionary<K, V>(builder.initialCapacity, builder.concurrencyLevel);
        }

        /// <summary>
        /// 构建一个支持原子的、后台计算值的字典，获取方法将获取一个值，这个值自动使用计算器
        /// 传递给builder的Func计算，或者等待其他线程计算值。在一个给定时间内，每一个key
        /// 仅仅一个值被计算，如果实体的值没有完成计算，除了Get的其他查询方法都将立即返回，这是
        /// 因为实体并不存在。换句话说，实体必须在计算完成后外部可见。Get方法抛出：
        /// <list>
        ///  <li>NullPointerException:如果key为null，或者计算器返回null</li>
        ///  <li>ComputationException:计算期间打包的异常</li>
        /// </list>
        /// 如果设置方法在计算完成前调用，其他等待的线程将被唤醒并优先返回放入的值，在这个时间点
        /// 上，计算的结果将覆盖设置方法设置的值
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="V"></typeparam>
        /// <param name="computer"></param>
        /// <returns></returns>
        public ConcurrentMap<K, V> MakeComputingMap<K, V>(Func<K, V> computer)
            where K: class
            //where V:class
        {
            return new StrategyImpl<K, V>(this, computer).map;
        }

        /// <summary>
        /// 表示引用字典的一个实体
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="V"></typeparam>
        public interface ReferenceEntry<K, V>
        {
            /// <summary>
            /// 获取/设置实体中的值引用对象
            /// </summary>
            ValueReference<K, V> ValueReference
            {
                get;
                set;
            }

            /// <summary>
            /// 如果值引用没有改变，则从字典中删除此实体。用于在值之后执行清理。
            /// 值引用在实体中调用此方法以便其无需保持他拥有的引用
            /// </summary>
            void ValueReclaimed();

            /// <summary>
            /// 获取链表中的下一个实体
            /// </summary>
            /// <returns></returns>
            ReferenceEntry<K, V> Next
            {
                get;
            }

            int Hash
            {
                get;
            }

            K Key
            {
                get;
            }
        }

        /// <summary>
        /// 一个值的引用接口
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="V"></typeparam>
        public interface ValueReference<K, V>
        {
            /// <summary>
            /// 获取值，不会阻塞或抛出异常
            /// </summary>
            /// <returns></returns>
            V Get();

            /// <summary>
            /// 创建一个对给定实体的此引用的拷贝
            /// </summary>
            /// <param name="entry"></param>
            /// <returns></returns>
            ValueReference<K, V> CopyFor(ReferenceEntry<K, V> entry);

            /// <summary>
            /// 等待一个仍然在计算的值。他不同于Get方法，此方法将可能阻塞（
            /// FutureValueReference情形）或抛出中断InterruptedException异常
            /// </summary>
            /// <returns></returns>
            V WaitForValue();
        }

        //internal static readonly ValueReference<object, object> COMPUTING = new ComputingValueReerence();

        internal class ComputingValueReerence<K, V> : ValueReference<K, V>
        {
            public ValueReference<K, V> CopyFor(ReferenceEntry<K, V> entry)
            {
                throw new NotSupportedException();
            }

            V ValueReference<K, V>.Get()
            {
                return default(V);
            }

            V ValueReference<K, V>.WaitForValue()
            {
                throw new NotSupportedException();
            }

            public override bool Equals(object obj)
            {
                if (obj is ComputingValueReerence<K, V>)
                {
                    return true;//TODO:所有计算的值引用都相等！
                }
                return false;
            }
        }

        /// <summary>
        /// 单例占位器用于指定一个正在被计算的值，此方法永远不会返回一个非null的值
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="V"></typeparam>
        /// <returns></returns>
        private static ValueReference<K, V> Computing<K, V>()
        {
            return new ComputingValueReerence<K, V>();
        }

        /// <summary>
        /// 用于提供null输出异常给其他线程
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="V"></typeparam>
        internal class NullOutputExceptionReference<K, V> : ValueReference<K, V>
        {
            readonly string message;
            internal NullOutputExceptionReference(string message)
            {
                this.message = message;
            }
            public V Get()
            {
                return default(V);
            }
            public ValueReference<K, V> CopyFor(ReferenceEntry<K, V> entry)
            {
                return this;
            }
            public V WaitForValue()
            {
                throw new NullOutputException(message);
            }
        }

        /// <summary>
        /// 用于给其他线程提供计算异常
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="V"></typeparam>
        internal class ComputationExceptionReference<K, V> : ValueReference<K, V>
        {
            readonly Exception t;
            internal ComputationExceptionReference(Exception t)
            {
                this.t = t;
            }
            public V Get()
            {
                return default(V);
            }
            public ValueReference<K, V> CopyFor(ReferenceEntry<K, V> entry)
            {
                return this;
            }
            public V WaitForValue()
            {
                throw new AsynchronousComputationException("waitforvalue exception", t);
            }
        }

        /// <summary>
        /// 用于弱引用的Key
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="V"></typeparam>
        internal class WeakEntry<K, V> : FinalizableWeakReference<K>, ReferenceEntry<K, V>
        {
            public WeakEntry(MapMaker mapMaker, CustomConcurrentDictionary.Internals<K, V, ReferenceEntry<K, V>> internals, K key, int hash)
                : base(key)
            {
                this.mapMaker = mapMaker;
                this.internals = internals;
                this.hash = hash;
                valueReference = Computing<K, V>();
            }

            public K Key
            {
                get
                {
                    return (K)this.Target;
                }
            }

            // The code below is exactly the same for each entry type.
            protected MapMaker mapMaker;
            internal readonly CustomConcurrentDictionary.Internals<K, V, ReferenceEntry<K, V>> internals;
            readonly int hash;
            volatile ValueReference<K, V> valueReference;

            public virtual ValueReference<K, V> ValueReference
            {
                get
                {
                    return valueReference;
                }
                set
                {
                    this.valueReference = value;
                }
            }

            public virtual void ValueReclaimed()
            {
                internals.RemoveEntry(this, default(V));
            }

            public virtual ReferenceEntry<K, V> Next
            {
                get
                {
                    return null;
                }
            }

            public virtual int Hash
            {
                get { return hash; }
            }

            public override void FinalizeReferent()
            {
                internals.RemoveEntry(this);
            }
        }

        internal class LinkedWeakEntry<K, V> : WeakEntry<K, V>
        {
            public LinkedWeakEntry(MapMaker maker, CustomConcurrentDictionary.Internals<K, V, ReferenceEntry<K, V>> internals,
                K key, int hash, ReferenceEntry<K, V> next)
                : base(maker, internals, key, hash)
            {
                this.next = next;
            }

            readonly ReferenceEntry<K, V> next;

            public override ReferenceEntry<K, V> Next
            {
                get
                {
                    return next;
                }
            }
        }

        /// <summary>
        /// 用于强引用的key
        /// </summary>
        /// <typeparam name="K"></typeparam>
        /// <typeparam name="V"></typeparam>
        internal class StrongEntry<K, V> : ReferenceEntry<K, V>
        {
            readonly K key;

            internal StrongEntry(MapMaker maker, CustomConcurrentDictionary.Internals<K, V, ReferenceEntry<K, V>> internals, K key, int hash)
            {
                this.internals = internals;
                this.key = key;
                this.hash = hash;
                this.mapMaker = maker;
                this.valueReference = Computing<K, V>();
            }

            public K Key
            {
                get
                {
                    return this.key;
                }
            }

            // The code below is exactly the same for each entry type.
            protected readonly MapMaker mapMaker;
            internal readonly CustomConcurrentDictionary.Internals<K, V, ReferenceEntry<K, V>> internals;
            readonly int hash;
            volatile ValueReference<K, V> valueReference;

            public virtual ValueReference<K, V> ValueReference
            {
                get
                {
                    return valueReference;
                }
                set
                {
                    this.valueReference = value;
                }
            }

            public virtual void ValueReclaimed()
            {
                internals.RemoveEntry(this, default(V));
            }
            public virtual ReferenceEntry<K, V> Next
            {
                get
                {
                    return null;
                }
            }
            public virtual int Hash
            {
                get
                {
                    return hash;
                }
            }
        }

        internal class LinkedStrongEntry<K, V> : StrongEntry<K, V>
        {

            internal LinkedStrongEntry(MapMaker maker, CustomConcurrentDictionary.Internals<K, V, ReferenceEntry<K, V>> internals,
                K key, int hash, ReferenceEntry<K, V> next)
                : base(maker, internals, key, hash)
            {
                this.next = next;
            }

            readonly ReferenceEntry<K, V> next;

            public override ReferenceEntry<K, V> Next
            {
                get
                {
                    return next;
                }
            }
        }


        /** 引用一个弱值. */
        internal class WeakValueReference<K, V> : FinalizableWeakReference<V>, ValueReference<K, V>
            //where V : class
        {
            readonly ReferenceEntry<K, V> entry;

            internal WeakValueReference(V referent, ReferenceEntry<K, V> entry)
                : base(referent)
            {
                this.entry = entry;
            }

            public override void FinalizeReferent()
            {
                entry.ValueReclaimed();
            }

            public ValueReference<K, V> CopyFor(ReferenceEntry<K, V> entry)
            {
                return new WeakValueReference<K, V>((V)this.Target, entry);
            }

            public V WaitForValue()
            {
                return (V)this.Target;
            }

            public V Get()
            {
                return (V)this.Target;
            }
        }

        /** References a strong value. */
        internal class StrongValueReference<K, V> : ValueReference<K, V>
        {
            readonly V referent;

            internal StrongValueReference(V referent)
            {
                this.referent = referent;
            }

            public V Get()
            {
                return referent;
            }

            public ValueReference<K, V> CopyFor(ReferenceEntry<K, V> entry)
            {
                return this;
            }

            public V WaitForValue()
            {
                return Get();
            }
        }

        internal abstract class Strength
        {
            public abstract bool Equal(object a, object b);

            public abstract int Hash(object o);

            public abstract ValueReference<K, V> ReferenceValue<K, V>(ReferenceEntry<K, V> entry, V value) /*where V : class*/;

            public abstract ReferenceEntry<K, V> NewEntry<K, V>(CustomConcurrentDictionary.Internals<K, V, ReferenceEntry<K, V>> internals, K key, int hash, ReferenceEntry<K, V> next);

            public abstract ReferenceEntry<K, V> CopyEntry<K, V>(K key, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext);
        }

        internal class WeakStrength : Strength
        {
            private MapMaker maker;

            public WeakStrength(MapMaker maker)
            {
                this.maker = maker;
            }

            public override bool Equal(object a, object b)
            {
                return a == b;
            }

            public override int Hash(object o)
            {
                return o.GetHashCode();
            }

            public override bool Equals(object obj)
            {
                if (!(obj is WeakStrength))
                {
                    return false;
                }
                WeakStrength ws = obj as WeakStrength;
                return maker == ws.maker;
            }

            public override int GetHashCode()
            {
                return maker.GetHashCode();
            }

            //
            public override ValueReference<K, V> ReferenceValue<K, V>(ReferenceEntry<K, V> entry, V value)
            {
                return new WeakValueReference<K, V>(value, entry);
            }

            public override ReferenceEntry<K, V> NewEntry<K, V>(CustomConcurrentDictionary.Internals<K, V, ReferenceEntry<K, V>> internals, K key, int hash, ReferenceEntry<K, V> next)
            {
                return (next == null) ? new WeakEntry<K, V>(this.maker, internals, key, hash) : new LinkedWeakEntry<K, V>(this.maker, internals, key, hash, next);
            }

            public override ReferenceEntry<K, V> CopyEntry<K, V>(K key, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext)
            {
                WeakEntry<K, V> from = (WeakEntry<K, V>)original;
                return (newNext == null) ? new WeakEntry<K, V>(this.maker, from.internals, key, from.Hash) : new LinkedWeakEntry<K, V>(this.maker, from.internals, key, from.Hash, newNext);
            }
        }

        internal class StrongStrength : Strength
        {
            private MapMaker maker;

            public StrongStrength(MapMaker maker)
            {
                this.maker = maker;
            }

            public override bool Equal(object a, object b)
            {
                return a.Equals(b);
            }

            public override int Hash(object o)
            {
                return o.GetHashCode();
            }

            public override bool Equals(object obj)
            {
                if (!(obj is StrongStrength))
                {
                    return false;
                }
                StrongStrength ws = obj as StrongStrength;
                return maker == ws.maker;
            }

            public override int GetHashCode()
            {
                return maker.GetHashCode();
            }

            //
            public override ValueReference<K, V> ReferenceValue<K, V>(ReferenceEntry<K, V> entry, V value)
            {
                return new StrongValueReference<K, V>(value);
            }

            public override ReferenceEntry<K, V> NewEntry<K, V>(CustomConcurrentDictionary.Internals<K, V, ReferenceEntry<K, V>> internals, K key, int hash, ReferenceEntry<K, V> next)
            {
                return (next == null)
                         ? new StrongEntry<K, V>(maker, internals, key, hash)
                         : new LinkedStrongEntry<K, V>(maker, internals, key, hash, next);
            }

            public override ReferenceEntry<K, V> CopyEntry<K, V>(K key, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext)
            {
                StrongEntry<K, V> from = (StrongEntry<K, V>)original;
                return (newNext == null)
                    ? new StrongEntry<K, V>(maker, from.internals, key, from.Hash)
                    : new LinkedStrongEntry<K, V>(maker, from.internals, key, from.Hash, newNext);
            }
        }

        [Serializable]
        internal class StrategyImpl<K, V> : CustomConcurrentDictionary.ComputingStrategy<K, V, ReferenceEntry<K, V>>
            where K: class
            //where V : class
        {
            internal readonly Strength keyStrength;
            internal readonly Strength valueStrength;
            internal readonly ConcurrentMap<K, V> map;
            internal readonly long expirationNanos;
            internal CustomConcurrentDictionary.Internals<K, V, ReferenceEntry<K, V>> internals;

            /// <summary>
            /// 反序列化：keyStrength\valueStrength\expirationNanos\internals\map
            /// </summary>
            /// <param name="info"></param>
            /// <param name="ctxt"></param>
            public StrategyImpl(SerializationInfo info, StreamingContext ctxt) 
            {
                Fields.keyStrength.SetValue(this, info.GetValue("keyStrength", typeof(Strength)));
                Fields.valueStrength.SetValue(this, info.GetValue("valueStrength", typeof(Strength)));
                Fields.expirationNanos.SetValue(this, info.GetInt64("expirationNanos"));
                Fields.internals.SetValue(this, info.GetValue("internals", typeof(CustomConcurrentDictionary.Internals<K, V, ReferenceEntry<K, V>>)));
                Fields.map.SetValue(this, info.GetValue("map", typeof(ConcurrentMap<K, V>)));
            }

            public StrategyImpl(MapMaker maker)
            {
                this.keyStrength = maker.keyStrength;
                this.valueStrength = maker.valueStrength;
                this.expirationNanos = maker.expirationNanos;

                map = maker.builder.BuildDictionary<K, V, ReferenceEntry<K, V>>(this);
            }

            public StrategyImpl(MapMaker maker, Func<K, V> computer)
            {
                this.keyStrength = maker.keyStrength;
                this.valueStrength = maker.valueStrength;
                this.expirationNanos = maker.expirationNanos;

                map = maker.builder.BuildComputingDictionary<K, V, ReferenceEntry<K, V>>(this, computer);
            }

            public void SetValue(ReferenceEntry<K, V> entry, V value)
            {
                SetValueReference(entry, valueStrength.ReferenceValue(entry, value));
                if (expirationNanos > 0)
                {
                    ScheduleRemoval(entry.Key, value);
                }
            }

            void ScheduleRemoval(K key, V value)
            {
                /*
                 * TODO: Keep weak reference to map, too. Build a priority
                 * queue out of the entries themselves instead of creating a
                 * task per entry. Then, we could have one recurring task per
                 * map (which would clean the entire map and then reschedule
                 * itself depending upon when the next expiration comes). We
                 * also want to avoid removing an entry prematurely if the
                 * entry was set to the same value again.
                 */
                WeakReference keyReference = new WeakReference(key);
                WeakReference valueReference = new WeakReference(value);
                //将时间间隔转换为指定的毫秒后，运行一次任务
                ExpirationTimer.Schedule((o, e) =>
                {
                    K k = keyReference.Target as K;
                    if (k != null)
                    {
                        // Remove if the value is still the same.
                        map.Remove(k, ((V)valueReference.Target));
                    }
                }, new TimeSpan(expirationNanos).Milliseconds);
            }

            public bool EqualKeys(K a, Object b)
            {
                return keyStrength.Equal(a, b);
            }

            public bool EqualValues(V a, Object b)
            {
                return valueStrength.Equal(a, b);
            }

            public int HashKey(Object key)
            {
                return keyStrength.Hash(key);
            }

            public K GetKey(ReferenceEntry<K, V> entry)
            {
                return entry.Key;
            }

            public int GetHash(ReferenceEntry<K, V> entry)
            {
                return entry.Hash;
            }

            public ReferenceEntry<K, V> NewEntry(K key, int hash, ReferenceEntry<K, V> next)
            {
                return keyStrength.NewEntry(internals, key, hash, next);
            }

            public ReferenceEntry<K, V> CopyEntry(K key, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext)
            {
                ValueReference<K, V> valueReference = original.ValueReference;
                if (valueReference.Equals(new ComputingValueReerence<K, V>()))
                {
                    ReferenceEntry<K, V> newEntry = NewEntry(key, original.Hash, newNext);
                    newEntry.ValueReference = new FutureValueReference(this, original, newEntry);
                    return newEntry;
                }
                else
                {
                    ReferenceEntry<K, V> newEntry = NewEntry(key, original.Hash, newNext);
                    newEntry.ValueReference = valueReference.CopyFor(newEntry);
                    return newEntry;
                }
            }

            /// <summary>
            /// 等待计算线程完成并返回计算的结果，如果没有有效结果，将返回null
            /// </summary>
            /// <param name="entry"></param>
            /// <returns></returns>
            /// <exception cref="ThreadInterruptedException">等待线程中断</exception>
            public V WaitForValue(ReferenceEntry<K, V> entry)
            {
                ValueReference<K, V> valueReference = entry.ValueReference;
                if (valueReference.Equals(new ComputingValueReerence<K, V>()))
                {
                    try
                    {
                        Monitor.Enter(entry);
                        while ((valueReference = entry.ValueReference).Equals(new ComputingValueReerence<K, V>()))
                        {
                            Monitor.Wait(entry);
                        }
                    }
                    finally
                    {
                        Monitor.Exit(entry);
                    }
                }
                return valueReference.WaitForValue();
            }

            /// <summary>
            /// 用于CustomConcurrentHashMap获取值。当阻塞时将返回null或抛出异常
            /// </summary>
            /// <param name="entry"></param>
            /// <returns></returns>
            public V GetValue(ReferenceEntry<K, V> entry)
            {
                ValueReference<K, V> valueReference = entry.ValueReference;
                return valueReference.Get();
            }

            public V Compute(K key, ReferenceEntry<K, V> entry, Func<K, V> computer)
            {
                V value;
                try
                {
                    value = computer(key);
                }
                catch (Exception t)
                {
                    SetValueReference(entry, new ComputationExceptionReference<K, V>(t));
                    throw new ComputationException("computing exception", t);
                }

                if (value == null)
                {
                    string message = computer + " returned null for key " + key + ".";
                    SetValueReference(entry, new NullOutputExceptionReference<K, V>(message));
                    throw new NullOutputException(message);
                }
                else
                {
                    SetValue(entry, value);
                }
                return value;
            }

            /// <summary>
            /// 在实体中设置值引用并通知其他等待的线程
            /// </summary>
            /// <param name="entry"></param>
            /// <param name="valueReference"></param>
            void SetValueReference(ReferenceEntry<K, V> entry, ValueReference<K, V> valueReference)
            {
                bool notifyOthers = (entry.ValueReference.Equals(new ComputingValueReerence<K, V>()));
                entry.ValueReference = valueReference;
                if (notifyOthers)
                {
                    try
                    {
                        Monitor.Enter(entry);
                        Monitor.PulseAll(entry);
                    }
                    finally
                    {
                        Monitor.Exit(entry);
                    }
                }
            }

            /// <summary>
            /// 当一个值正被计算时，指向一个旧实体。用于支持在扩充、删除期间非阻塞的拷贝实体
            /// </summary>
            internal class FutureValueReference : ValueReference<K, V>
            {
                readonly ReferenceEntry<K, V> original;
                readonly ReferenceEntry<K, V> newEntry;
                private StrategyImpl<K, V> strategyImpl;

                internal FutureValueReference(StrategyImpl<K, V> strategyImpl, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newEntry)
                {
                    this.original = original;
                    this.newEntry = newEntry;
                    this.strategyImpl = strategyImpl;
                }

                public V Get()
                {
                    bool success = false;
                    try
                    {
                        V value = original.ValueReference.Get();
                        success = true;
                        return value;
                    }
                    finally
                    {
                        if (!success)
                        {
                            RemoveEntry();
                        }
                    }
                }

                public ValueReference<K, V> CopyFor(ReferenceEntry<K, V> entry)
                {
                    return new FutureValueReference(this.strategyImpl, original, entry);
                }

                public V WaitForValue()
                {
                    bool success = false;
                    try
                    {
                        // assert that key != null
                        V value = this.strategyImpl.WaitForValue(original);
                        success = true;
                        return value;
                    }
                    finally
                    {
                        if (!success)
                        {
                            RemoveEntry();
                        }
                    }
                }

                /// <summary>
                /// 在异常时间中删除实体。理想情况下，我们在计算完成时要尽快清除，但
                /// 也有可能我们无法保持此实体的原始引用
                /// </summary>
                void RemoveEntry()
                {
                    this.strategyImpl.internals.RemoveEntry(newEntry);
                }
            }

            public ReferenceEntry<K, V> GetNext(ReferenceEntry<K, V> entry)
            {
                return entry.Next;
            }

            public void SetInternals(CustomConcurrentDictionary.Internals<K, V, ReferenceEntry<K, V>> internals)
            {
                this.internals = internals;
            }

            /// <summary>
            /// 序列化：keyStrength\valueStrength\expirationNanos\internals\map
            /// </summary>
            /// <param name="info"></param>
            /// <param name="context"></param>
            public void GetObjectData(SerializationInfo info, StreamingContext context)
            {
                //自定义序列化编码确保key和value strengths在map之前写入。我们需要他们反序列化map实体
                info.AddValue("keyStrength", keyStrength);
                info.AddValue("valueStrength", valueStrength);
                info.AddValue("expirationNanos", expirationNanos);
                // TODO: It is possible for the strategy to try to use the map
                // or internals during deserialization, for example, if an
                // entry gets reclaimed. We could detect this case and queue up
                // removals to be flushed after we deserialize the map.
                info.AddValue("internals", internals);
                info.AddValue("map", map);
            }

            /// <summary>
            /// 在反序列化期间使用的域。我们使用了一个嵌套的类，因此直到我们需要时才会加载他们。
            /// 我们需要使用反射来在构造器外部设置readonly域
            /// </summary>
            internal static class Fields
            {
                internal static readonly FieldInfo keyStrength = FindField("keyStrength");
                internal static readonly FieldInfo valueStrength = FindField("valueStrength");
                internal static readonly FieldInfo expirationNanos = FindField("expirationNanos");
                internal static readonly FieldInfo internals = FindField("internals");
                internal static readonly FieldInfo map = FindField("map");

                static FieldInfo FindField(string name)
                {
                    FieldInfo field = typeof(StrategyImpl<K, V>).GetField(name, BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.GetField);
                    if (field == null)
                        throw new NullReferenceException("the field:" + name + " not exist");
                    return field;
                }
            }
        }

    }

}
